package cn.sciento.export.filler;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import cn.sciento.export.ExcelFiller;
import cn.sciento.export.annotation.ExcelSheet;
import cn.sciento.export.vo.ExportColumn;
import org.springframework.util.Assert;


/**
 * @deprecated
 */
@Deprecated
public class SingleSheetStructureFiller extends ExcelFiller {
    public static final String FILLER_TYPE = "single-sheet-structure";
    private CellStyle childTitleCellStyle;
    private int currentSheetIndex;
    private int childCount = 0;

    public SingleSheetStructureFiller() {
    }

    public SingleSheetStructureFiller(SXSSFWorkbook workbook) {
        super(workbook);
        this.setChildTitleCellStyle();
    }

    public String getFillerType() {
        return "single-sheet-structure";
    }

    public void fillData(SXSSFWorkbook workbook, ExportColumn exportClass, List<?> data) {
        if (data != null) {
            if (workbook.getNumberOfSheets() == 0) {
                this.childCount = this.getCheckedChildren(exportClass).size();
            }

            this.fillData(exportClass, exportClass.getExcelSheet().colOffset(), data);
            ++this.currentSheetIndex;
        }
    }

    private void fillData(ExportColumn exportClass, int colOffset, List<?> data) {
        SXSSFSheet sheet = this.workbook.getSheetAt(this.currentSheetIndex);
        List<ExportColumn> checkedChildren = this.getCheckedChildren(exportClass);
        int i = 0;

        for (int len = data.size(); i < len; ++i) {
            Assert.isTrue(sheet.getLastRowNum() < 1000000, "export.too-many-data");
            SXSSFRow row = sheet.createRow(sheet.getLastRowNum() + 1);
            this.fillRow(row, colOffset, exportClass.getExcelSheet().placeholder(), data.get(i), exportClass.getChildren());
            Iterator var9 = checkedChildren.iterator();

            while (var9.hasNext()) {
                ExportColumn child = (ExportColumn) var9.next();
                List<Object> childData = this.getChildData(data.get(i), child);
                if (CollectionUtils.isNotEmpty(childData)) {
                    int childColOffset = child.getExcelSheet().colOffset() <= 0 ? 1 + colOffset : child.getExcelSheet().colOffset();
                    if (this.childCount > 1) {
                        this.createTitleRow(sheet, sheet.getLastRowNum() + 1, childColOffset, child.getExcelSheet().placeholder(), true, child.getChildren());
                    }

                    this.fillData(child, childColOffset, childData);
                }
            }
        }

    }

    public void createSheetAndTitle(SXSSFWorkbook workbook, ExportColumn exportClass) {
        SXSSFSheet sheet = workbook.createSheet((String) StringUtils.defaultIfBlank(exportClass.getTitle(), exportClass.getName()));
        sheet.setDefaultColumnWidth(20);
        int rowOffset = exportClass.getExcelSheet().rowOffset();
        int colOffset = exportClass.getExcelSheet().colOffset();
        this.createTitleRow(sheet, rowOffset, colOffset, (String) null, false, exportClass.getChildren());
        if (this.childCount == 1) {
            ExportColumn child = (ExportColumn) ((List) exportClass.getChildren().stream().filter(ExportColumn::hasChildren).collect(Collectors.toList())).get(0);
            ExcelSheet childSheet = child.getExcelSheet();
            int childRowOffset = childSheet.rowOffset() <= 0 ? 1 + rowOffset : childSheet.rowOffset();
            int childColOffset = childSheet.colOffset() <= 0 ? 1 + colOffset : childSheet.colOffset();
            this.createTitleRow(sheet, childRowOffset, childColOffset, childSheet.placeholder(), true, child.getChildren());
        }

    }

    private void createTitleRow(SXSSFSheet sheet, int rowOffset, int colOffset, String placeholder, boolean isChild, List<ExportColumn> columns) {
        SXSSFRow titleRow = sheet.createRow(rowOffset);

        int cellIndex;
        for (cellIndex = 0; cellIndex < colOffset; ++cellIndex) {
            if (isChild) {
                this.fillCellValue(titleRow.createCell(cellIndex), placeholder, Collections.emptyList(), (String) null, (List) null);
            }
        }

        Iterator var9 = columns.iterator();

        while (var9.hasNext()) {
            ExportColumn column = (ExportColumn) var9.next();
            if (column.isChecked() && !column.getExcelColumn().child()) {
                SXSSFCell cell = titleRow.createCell(cellIndex);
                this.fillCellValue(cell, column.getTitle(), Collections.emptyList(), column.getExcelColumn().pattern(), (List) null);
                if (isChild) {
                    cell.setCellStyle(this.childTitleCellStyle);
                } else {
                    titleRow.setHeight((short) 350);
                    cell.setCellStyle(this.titleCellStyle);
                }

                this.setCellWidth(sheet, column.getType(), cellIndex);
                ++cellIndex;
            }
        }

    }

    private void fillRow(SXSSFRow row, int colOffset, String placeholder, Object rowData, List<ExportColumn> columns) {
        int cellIndex;
        for (cellIndex = 0; cellIndex < colOffset; ++cellIndex) {
            this.fillCellValue(row.createCell(cellIndex), placeholder, (Object) null, (String) null, (List) null);
        }

        Iterator var7 = columns.iterator();

        while (var7.hasNext()) {
            ExportColumn column = (ExportColumn) var7.next();
            if (column.isChecked() && !column.hasChildren()) {
                String cellValue = null;

                try {
                    cellValue = BeanUtils.getProperty(rowData, column.getName());
                } catch (Exception var11) {
                    this.logger.error("get value error.", var11);
                }

                this.fillCellValue(row.createCell(cellIndex++), cellValue, rowData, column.getExcelColumn().pattern(), Arrays.asList(column.getExcelColumn().renderers()));
            }
        }

    }

    private List<ExportColumn> getCheckedChildren(ExportColumn root) {
        return root != null && CollectionUtils.isNotEmpty(root.getChildren()) ? (List) root.getChildren().stream().filter((column) -> {
            return column.isChecked() && column.hasChildren();
        }).collect(Collectors.toList()) : Collections.emptyList();
    }

    private List<Object> getChildData(Object data, ExportColumn child) {
        String getter = "get" + child.getName();
        Method[] methods = data.getClass().getDeclaredMethods();
        Method[] var5 = methods;
        int var6 = methods.length;

        for (int var7 = 0; var7 < var6; ++var7) {
            Method method = var5[var7];
            if (method.getName().equalsIgnoreCase(getter)) {
                try {
                    method.setAccessible(true);
                    return (List) method.invoke(data);
                } catch (Exception var10) {
                    this.logger.error("get child data error.", var10);
                }
            }
        }

        return Collections.emptyList();
    }

    protected void setChildTitleCellStyle() {
        Font font = this.workbook.createFont();
        font.setColor((short) 32767);
        this.childTitleCellStyle = this.workbook.createCellStyle();
        this.childTitleCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
        this.childTitleCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        this.childTitleCellStyle.setFont(font);
        this.childTitleCellStyle.setBorderTop(BorderStyle.THIN);
        this.childTitleCellStyle.setBorderBottom(BorderStyle.THIN);
    }
}
